﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CarbonExchange.WebControls
{
    [ToolboxData("<{0}:AmeeRepeater runat=server></{0}:AmeeRepeater>")]
    public class AmeeRepeater : CompositeControl, IPostBackEventHandler
    {
        private int NoOfItems { get; set; }

        public void SetNumberOfItems(int items)
        {
            NoOfItems = items;
        }

        public string ItemCssClass{get; set;}
        public bool AllowAdd { get; set; }
        public bool AllowRemove { get; set; }
        private string _ItemName = "Item";
        public string ItemName
        {
            get { return _ItemName; }
            set { _ItemName = value; }
        }
        //holds ids of items so that when an item is removed etc it does not change other items viewstate values
        private List<string> Ids = new List<string>();

        protected override void CreateChildControls()
        {
            for (int i = 0; i < NoOfItems; i++)
            {
                AddItem(i);
            }
            base.CreateChildControls();
        }

        private AmeeRepeaterItem AddItem(int index)
        {
            var item = new AmeeRepeaterItem();
            if (Ids.Count <= index)
            {
                //generate new id
                var n = index;
                string tmp = string.Concat(this.ID, "_", n);
                while (Ids.Contains(tmp))
                {
                    n++;
                    tmp = string.Concat(this.ID, "_", n);
                }
                Ids.Add(tmp);
            }
            item.ID = Ids[index];
            item.ItemIndex = index;
            item.CssClass = this.ItemCssClass;
            item.AllowRemove = this.AllowRemove;
            item.Repeater = this;
            this.Controls.Add(item);
            ItemTemplate.InstantiateIn(item);
            if (ItemCreated != null)
                ItemCreated(this, new ItemEventArgs(item));
            return item;
        }

        public AmeeRepeaterItem[] Items
        {
            get
            {
                return this.Controls.OfType<AmeeRepeaterItem>().ToArray();
            }
        }

        public override void DataBind()
        {
            foreach (var item in Items)
            {
                OnItemDataBinding(new ItemEventArgs(item));
                item.DataBind();
                OnItemDataBound(new ItemEventArgs(item));
            }
        }

        private void OnItemDataBinding(ItemEventArgs e)
        {
            if (ItemDataBinding != null)
                ItemDataBinding(this, e);
        }

        private void OnItemDataBound(ItemEventArgs e)
        {
            if (ItemDataBound != null)
                ItemDataBound(this, e);
        }

        [
        Browsable(false),
        DefaultValue(null),
        Description("The item template."),
        TemplateContainer(typeof(AmeeRepeaterItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate ItemTemplate{get;set;}

        protected override object SaveViewState()
        {
            ViewState["NoOfItems"] = NoOfItems;
            ViewState["Ids"] = Ids;
            return base.SaveViewState();
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            NoOfItems = (int)ViewState["NoOfItems"];
            Ids = (List<string>)ViewState["Ids"];
        }

        public event EventHandler<ItemEventArgs> ItemCreated;
        public event EventHandler<ItemEventArgs> ItemDataBound;
        public event EventHandler<ItemEventArgs> ItemDataBinding;
        public class ItemEventArgs : EventArgs
        {
            public ItemEventArgs(AmeeRepeaterItem item)
            {
                this.Item = item;
            }

            public AmeeRepeaterItem Item { get; private set; }
        }

        public event EventHandler<ItemEventArgs> ItemAdded;
        public event EventHandler<ItemEventArgs> ItemRemoved;

        protected override void OnPreRender(EventArgs e)
        {
            if (AllowAdd)
            {
                Page.RegisterRequiresRaiseEvent(this);
                /*var sm = ScriptManager.GetCurrent(this.Page);
                if (sm != null)
                {
                    sm.RegisterPostBackControl(this);
                }*/
            }

            base.OnPreRender(e);
        }
        protected override void Render(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "ameeRepeater");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);
            foreach (var item in this.Items)
            {
                item.RenderControl(writer);
            }
            //render add link
            if (AllowAdd)
            {
                //writer.AddAttribute(HtmlTextWriterAttribute.Class, "addItem");
                writer.RenderBeginTag(HtmlTextWriterTag.Span);
                writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.ClientScript.GetPostBackClientHyperlink(this, "Add"));
                writer.AddAttribute(HtmlTextWriterAttribute.Class, "addItem");
                writer.RenderBeginTag(HtmlTextWriterTag.A);
                writer.Write(string.Format("Add New {0}", ItemName));
                writer.RenderEndTag();
                writer.RenderEndTag();
            }
            writer.RenderEndTag();//Div
        }

        #region IPostBackEventHandler Members

        public void RaisePostBackEvent(string eventArgument)
        {
            if (eventArgument == "Add")
            {
                var tmp = AddItem(NoOfItems);
                NoOfItems++;
                //databind to create the controls within but dont ondatabind so that it dosnt get loaded with previosly saved data
                //TODO: Are you sure seems smelly
                tmp.DataBind();
                if (ItemAdded != null)
                {
                    ItemAdded(this, new ItemEventArgs(tmp));
                }
            }
        }

        #endregion

        private void RemoveItem(AmeeRepeaterItem item)
        {
            Ids.Remove(item.ID);
            NoOfItems--;
            if (ChildControlsCreated)
            {
                this.Controls.Remove(item);
                //set the itemindex of following items
                foreach (var otherItem in Items.Skip(item.ItemIndex))
                {
                    otherItem.ItemIndex--;
                }
            }
            if (ItemRemoved != null)
            {
                ItemRemoved(this, new ItemEventArgs(item));
            }
        }

        protected override bool OnBubbleEvent(object source, EventArgs args)
        {
            if (args is CommandEventArgs && source is AmeeRepeaterItem && ((CommandEventArgs)args).CommandName == "Remove")
            {
                RemoveItem((AmeeRepeaterItem)source);
                return false;
            }
            else
            {
                return base.OnBubbleEvent(source, args);
            }
        }
    }

    public class AmeeRepeaterItem : WebControl, INamingContainer, IPostBackEventHandler
    {
        public int ItemIndex { get; internal set; }
        public bool AllowRemove { get; internal set; }
        public AmeeRepeater Repeater {get; internal set;}
        protected override object SaveViewState()
        {
            ViewState["ItemIndex"] = ItemIndex;
            return base.SaveViewState();
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            ItemIndex = (int)ViewState["ItemIndex"];
        }

        protected override void OnPreRender(EventArgs e)
        {
            if (AllowRemove)
                Page.RegisterRequiresRaiseEvent(this);
            base.OnPreRender(e);
        }
        protected override void Render(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
            writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass);
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            writer.AddAttribute(HtmlTextWriterAttribute.Class, "titleArea_ameeSubQuestion clearfix");
            writer.RenderBeginTag(HtmlTextWriterTag.Span);


            writer.AddAttribute(HtmlTextWriterAttribute.Class, "title_ameeSubQuestion");
            writer.RenderBeginTag(HtmlTextWriterTag.Span);
                writer.Write(string.Format(this.Repeater.ItemName)+"-"+(this.ItemIndex+1));
            writer.RenderEndTag();
            
            if (AllowRemove)
            {
                //writer.AddAttribute(HtmlTextWriterAttribute.Class, "removeItem");
                
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.ClientScript.GetPostBackClientHyperlink(this, "Remove"));
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "removeItem");
                        //writer.AddAttribute(HtmlTextWriterAttribute.Alt, string.Format("Remove This {0}", this.Repeater.ItemName));
                        writer.AddAttribute(HtmlTextWriterAttribute.Title, string.Format("Remove This {0}", this.Repeater.ItemName));
                        writer.RenderBeginTag(HtmlTextWriterTag.A);
                        //writer.Write(string.Format("Remove This {0}", this.Repeater.ItemName));
                writer.RenderEndTag();
               
            }
            writer.RenderEndTag();
            base.RenderContents(writer);

            writer.RenderEndTag();
        }

        #region IPostBackEventHandler Members

        public void RaisePostBackEvent(string eventArgument)
        {
            if (eventArgument == "Remove")
            {
                base.RaiseBubbleEvent(this, new CommandEventArgs("Remove", null));
            }
        }

        #endregion
    }
}
